#include "server.h"

extern MYSQL* mySql;

// 核心函数在125行

int RegisterUser(Train_t* train, int peerFd, int* flag){
    //如果要注册，先接收用户提供的用户名
    memset(train, 0, sizeof(*train));
    int ret = recv(peerFd, &train->lenth, sizeof(int), MSG_WAITALL);
    RECV_ERROR_CHECK(ret);
    ret = recv(peerFd, train->buf, train->lenth, MSG_WAITALL);
    RECV_ERROR_CHECK(ret);
    //在数据库中查询该用户名，若数据库有重复的用户名，发送标志位提示重新输入
    //否则发送标志位提示继续输入密码
    char querySentence[2048] = {0};
    sprintf(querySentence, "select count(id) from user where username = '%s'", train->buf);
    ret = mysql_query(mySql, querySentence);
    MYSQL_ERROR_CHECK(ret, mySql);
    MYSQL_RES* result = mysql_store_result(mySql);
    MYSQL_ERROR_CHECK_RESULT(result, mysql);
    MYSQL_ROW row = mysql_fetch_row(result);
    if(strcmp(row[0], "0") == 0) {
        *flag = 0;
    } else {
        *flag = 1;
    }
    sendn(peerFd, flag, sizeof(int));
    mysql_free_result(result);
}

int RegisterMsg(Train_t* train, int peerFd, int* userId){
    //将用户名写入缓冲区，再接收用户提供的密码
    char username[1024] = {0};
    strcpy(username, train->buf);
    memset(train, 0, sizeof(*train));
    int ret = recv(peerFd, &train->lenth, sizeof(int), MSG_WAITALL);
    RECV_ERROR_CHECK(ret);
    ret = recv(peerFd, train->buf, train->lenth, MSG_WAITALL);
    RECV_ERROR_CHECK(ret);
    //生成盐值，并对用户密码加密，并保存到缓冲区
    char salt[SALT_SIZE + 1] = {0};
    char cryptpasswd[1024] = {0};
    GenerateSalt(salt);
    strcpy(cryptpasswd, crypt(train->buf, salt));
    //向数据库写入用户信息
    char querySentence[2048] = {0};
    sprintf(querySentence, 
            "insert into user (username, salt, cryptpasswd, pwd) values ('%s', '%s', '%s', '~')", 
            username, salt, cryptpasswd);
    ret = mysql_query(mySql, querySentence);
    MYSQL_ERROR_CHECK(ret, mySql);
    //获取用户id
    memset(querySentence, 0, sizeof(querySentence));
    sprintf(querySentence, "select id from user where username = '%s'", username);
    ret = mysql_query(mySql, querySentence);
    MYSQL_ERROR_CHECK(ret, mySql);
    MYSQL_RES* result = mysql_store_result(mySql);
    MYSQL_ERROR_CHECK_RESULT(result, mysql);
    MYSQL_ROW row = mysql_fetch_row(result);
    *userId = atoi(row[0]);
    mysql_free_result(result);
    
    //在虚拟文件系统中为新用户创建根目录
    memset(querySentence, 0, sizeof(querySentence));
    sprintf(querySentence, 
            "insert into filesystem (parent_id, filename, owner_id, md5, filesize, type) values (-1, '~', %d, '0', 0, 0)", 
            *userId);
    ret = mysql_query(mySql, querySentence);
    MYSQL_ERROR_CHECK(ret, mySql);
}

int LoginUser(Train_t* train, int peerFd, int* flag){
    //如果要登录，先接收用户提供的用户名
    memset(train, 0, sizeof(*train));
    int ret = recv(peerFd, &train->lenth, sizeof(int), MSG_WAITALL);
    RECV_ERROR_CHECK(ret);
    ret = recv(peerFd, train->buf, train->lenth, MSG_WAITALL);
    RECV_ERROR_CHECK(ret);
    //在数据库中查询该用户名，若数据库没有该用户名，发送标志位提示重新输入
    //否则发送标志位提示继续输入密码
    char querySentence[2048] = {0};
    sprintf(querySentence, "select count(id) from user where username = '%s'", train->buf);
    ret = mysql_query(mySql, querySentence);
    MYSQL_ERROR_CHECK(ret, mySql);
    MYSQL_RES* result = mysql_store_result(mySql);
    MYSQL_ERROR_CHECK_RESULT(result, mysql);
    MYSQL_ROW row = mysql_fetch_row(result);
    if(strcmp(row[0], "0") == 0) {
        *flag = 0;
    } else {
        *flag = 1;
    }
    sendn(peerFd, flag, sizeof(int));
    mysql_free_result(result);
}

int LoginInSql(Train_t* train, int peerFd, char* username, int* flag, int* userId){
    memset(train, 0, sizeof(*train));
    int ret = recv(peerFd, &train->lenth, sizeof(int), MSG_WAITALL);
    RECV_ERROR_CHECK(ret);
    ret = recv(peerFd, train->buf, train->lenth, MSG_WAITALL);
    RECV_ERROR_CHECK(ret);
    //从数据库中找到用户名对应的盐值和密码的密文
    char cryptpasswd[1024] = {0};
    char querySentence[2048] = {0};
    sprintf(querySentence, "select salt, cryptpasswd, id from user where username = '%s'", username);
    ret = mysql_query(mySql, querySentence);
    MYSQL_ERROR_CHECK(ret, mySql);
    MYSQL_RES* result = mysql_store_result(mySql);
    MYSQL_ERROR_CHECK_RESULT(result, mysql);
    MYSQL_ROW row = mysql_fetch_row(result);
    strcpy(cryptpasswd, crypt(train->buf, row[0]));
    //将数据库中的密文和用户发送的密码对应的密文进行比较，如果相同则登录成功，不同则提示用户重新输入
    if(strcmp(cryptpasswd, row[1]) == 0) {
        *flag = 0;
        *userId = atoi(row[2]);
    } else {
        *flag = 1;
    }
    sendn(peerFd, &flag, sizeof(int));
    mysql_free_result(result);
}


int Register(int peerFd) {
    //接收标志位信息确定用户是要登录还是注册
    int flag;
    int userId = -1;
    int ret = recv(peerFd, &flag, sizeof(int), MSG_WAITALL);
    RECV_ERROR_CHECK(ret);
    //根据用户提供的数字判断是登录还是注册
    Train_t train;
    if(flag == 0) {
        do{
            // 注册用户
            RegisterUser(&train, peerFd, &flag);
        } while(flag == 1);
        // 把用户信息写入数据库
        RegisterMsg(&train, peerFd, &userId);
    } else {
        do{
            // 登陆用户
            LoginUser(&train, peerFd, &flag);
        } while(flag == 0);
        //将用户名写入缓冲区，再接收用户提供的密码
        char username[1024] = {0};
        strcpy(username, train.buf);
        do{
            // 与数据库进行比较
            LoginInSql(&train, peerFd, username, &flag, &userId);
        } while(flag == 1);
    }
    //登陆成功，需要把用户的当前工作目录修改为~
    char querySentence[2048] = {0};
    sprintf(querySentence, "update user set pwd = '~' where id = %d", userId);
    ret = mysql_query(mySql, querySentence);
    MYSQL_ERROR_CHECK(ret, mySql);
    return userId;
}

void GenerateSalt(char* salt) {
    int flag;
    srand(time(NULL));
    for(int i = 0; i < SALT_SIZE; i++) {
        flag = rand() % 3;
        switch(flag) {
        case 0: salt[i] = rand() % 26 + 'a'; break;
        case 1: salt[i] = rand() % 26 + 'A'; break;
        case 2: salt[i] = rand() % 10 + '0'; break;
        }
    }
}
